﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Security;


using System.Xml.Linq;
using System.Xml;
using System.Collections;
using System.Globalization;
using System.IO;

using SPBusiness.ExtensionMethods;
using System.Collections.ObjectModel;

namespace SPBusiness
{
   /// <summary>
   /// 
   /// </summary>
   public sealed class ElementDefinition
   {


      /// <summary>
      /// ElementDefinition class has only Static Methods, no constructor needed.
      /// </summary>
      private ElementDefinition() { }

      public static void UpdateFilesInModule(SPWeb pSPWeb, SPElementDefinition pSPElementDefinition)
      {
         try
         {
            XElement xml = pSPElementDefinition.XmlDefinition.ToXElement();
            XNamespace xmlns = "http://schemas.microsoft.com/sharepoint/";
            string featureDir = pSPElementDefinition.FeatureDefinition.RootDirectory;
            CustomSPModule module = (from m in xml.DescendantsAndSelf()
                                     select new CustomSPModule
                                     {
                                        ProvisioningUrl = m.Attribute("Url").Value,
                                        PhysicalPath = Path.Combine(featureDir, m.Attribute("Path").Value),
                                        Files = new CustomSPModuleFileCollection((from f in m.Elements(xmlns.GetName("File"))
                                                                                  select new CustomSPModuleFile
                                                                                  {
                                                                                     Name = f.Attribute("Url").Value,
                                                                                     Properties = (from p in f.Elements(xmlns.GetName("Property"))
                                                                                                   select p).ToDictionary(
                                                                                                     n => n.Attribute("Name").Value,
                                                                                                     v => v.Attribute("Value").Value)
                                                                                  }).ToList<CustomSPModuleFile>())
                                     }).First();

            if (module == null)
            {
               return;
            }

            foreach (CustomSPModuleFile file in module.Files)
            {
               string physicalPath = Path.Combine(module.PhysicalPath, file.Name);
               string virtualPath = string.Concat(pSPWeb.Url, "/", module.ProvisioningUrl, "/", file.Name);

               if (System.IO.File.Exists(physicalPath))
               {
                  using (StreamReader sreader = new StreamReader(physicalPath))
                  {

                     File.CheckOut(pSPWeb.GetFile(virtualPath));

                     SPFile spFile = pSPWeb.Files.Add(virtualPath, sreader.BaseStream, new Hashtable(file.Properties), true);

                     File.Approve(spFile);
                  }
               }
            }
         }
         catch (Exception ex)
         {
            Logging.LogMessase(typeof(ElementDefinition).Namespace, typeof(ElementDefinition).Name, "UpdateFilesInModule", ex);
            throw;
         }
      }

      public static void UpdateFilesInModule(SPWeb pSPWeb, Guid pFeatureDefinitionId, string pElementType, string pElementName)
      {
         try
         {
            SPElementDefinition vSPElementDefinition = null;

            vSPElementDefinition = GetElementDefinition(pSPWeb, pFeatureDefinitionId, pElementType, pElementName);

            if (vSPElementDefinition != null)
            {
               UpdateFilesInModule(pSPWeb, vSPElementDefinition);
            }

         }
         catch (Exception ex)
         {
            Logging.LogMessase(typeof(ElementDefinition).Namespace, typeof(ElementDefinition).Name, "UpdateFilesInModule", ex);
            throw;
         }
      }

      public static SPElementDefinition GetElementDefinition(SPWeb pSPWeb, Guid pFeatureDefinitionId, string pElementType, string pElementName)
      {
         try
         {

            SPElementDefinition Return = null;

            SPFeatureDefinition vSPFeatureDefinition = Feature.GetSPFeatureDefinition(pSPWeb, pFeatureDefinitionId);

            if (vSPFeatureDefinition != null)
            {
               SPElementDefinitionCollection vSPElementDefinitionCollection = vSPFeatureDefinition.GetElementDefinitions(CultureInfo.CurrentCulture);

               foreach (SPElementDefinition vSPElementDefinition in vSPElementDefinitionCollection)
               {
                  if (vSPElementDefinition.ElementType == pElementType && vSPElementDefinition.Id == pElementName)
                  {
                     Return = vSPElementDefinition;
                     break;
                  }
               }


            }

            return Return;
         }
         catch (Exception ex)
         {
            Logging.LogMessase(typeof(ElementDefinition).Namespace, typeof(ElementDefinition).Name, "GetElementDefinition", ex);
            throw;
         }
      }

      private class CustomSPModule
      {
         public string ProvisioningUrl { get; set; }
         public string PhysicalPath { get; set; }
         public CustomSPModuleFileCollection Files { get; set; }
      }

      private class CustomSPModuleFile
      {
         public string Name { get; set; }
         public Dictionary<string, string> Properties { get; set; }
      }


      private class CustomSPModuleFileCollection : Collection<CustomSPModuleFile>
      {
         public CustomSPModuleFileCollection()
            : base()
         {
         }

         public CustomSPModuleFileCollection(IList<CustomSPModuleFile> pCustomSPModuleFileList)
            : base(pCustomSPModuleFileList)
         { }
      }

   }
}
